package com.itheima.app.manager;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Comment;
import com.itheima.domain.mongo.Movement;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.CommentService;
import com.itheima.service.mongo.MovementService;
import com.itheima.util.ConstantUtil;
import com.itheima.vo.CommentVo;
import com.itheima.vo.MovementVo;
import com.itheima.vo.PageBeanVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
public class MovementManager {

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementService movementService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private MQMovementManager mqMovementManager;

    // 发布动态
    public ResponseEntity saveMovement(Movement movement, MultipartFile[] imageContent) throws IOException {

        //先查redis中是否冻结了发布动态
        if (stringRedisTemplate.hasKey("freeze:publish")) {

            return ResponseEntity.status(500).body("禁止发布动态");
        }

        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.将图片上传到阿里云
        List<String> medias = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String picUrl = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            medias.add(picUrl);
        }
        // 3.补充movement实体
        movement.setId(ObjectId.get()); // 主键id
        movement.setUserId(userId); // 发布人id
        movement.setMedias(medias); // 动态图片
        movement.setState(0); // 待审核
        movement.setCreated(System.currentTimeMillis()); // 发布时间
        movement.setSeeType(1); // v1.0版本 公开
        // 4.调用rpc发布动态
        movementService.saveMovement(movement);

        // 5.发送mq消息（审核）
        rabbitTemplate.convertAndSend("tanhua.movement.state", movement.getId().toHexString());

        // 6.发送mq消息（推荐）
        mqMovementManager.sendMovement(movement.getUserId(), movement.getId(), MQMovementManager.MOVEMENT_PUBLISH);

        return ResponseEntity.ok("发布动态成功");
    }

    @DubboReference
    private UserInfoService userInfoService;

    // 查询个人动态
    public ResponseEntity findMyMovementByPage(Long userId, Integer pageNum, Integer pageSize) {
        // 1.查询动态详情
        PageBeanVo pageBeanVo = movementService.findMyMovementByPage(userId, pageNum, pageSize);
        // 2.封装MovementVo
        // 2-1 声明voList
        List<MovementVo> voList = new ArrayList<>();
        // 2-2 获取movementList
        List<Movement> movementList = (List<Movement>) pageBeanVo.getItems();
        // 2-3 遍历movementList
        if (CollectionUtil.isNotEmpty(movementList)) {
            for (Movement movement : movementList) {
                // 根据用户id查询userInfo
                UserInfo userInfo = userInfoService.findByUserId(movement.getUserId());
                // 创建vo并封装,注意：userInfo必须在上，movement必须在下
                MovementVo vo = new MovementVo();
                vo.setUserInfo(userInfo);
                vo.setMovement(movement);

                // 点赞是否标记
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, userId, movement.getId().toHexString()))) {
                    vo.setHasLiked(1);
                }

                // 添加得到voList
                voList.add(vo);
            }
        }
        // 3.将voList设置到分页对象
        pageBeanVo.setItems(voList);

        // 4.返回分页对象
        return ResponseEntity.ok(pageBeanVo);
    }

    // 查询好友动态
    public ResponseEntity findFriendMovementByPage(Integer pageNum, Integer pageSize) {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.调用rpc查询好友动态详情
        PageBeanVo pageBeanVo = movementService.findFriendMovementByPage(userId, pageNum, pageSize);
        // 3.封装movmenetVo
        // 3-1 声明voList
        List<MovementVo> voList = new ArrayList<>();
        // 3-2 获取movementList
        List<Movement> movementList = (List<Movement>) pageBeanVo.getItems();
        // 3-3 遍历movementList
        if (CollectionUtil.isNotEmpty(movementList)) {
            for (Movement movement : movementList) {
                // 查询userInfo
                UserInfo userInfo = userInfoService.findByUserId(movement.getUserId());
                // 创建vo 先userInfo 再 movement
                MovementVo vo = new MovementVo();
                vo.setUserInfo(userInfo);
                vo.setMovement(movement);
                // 点赞是否标记
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, userId, movement.getId().toHexString()))) {
                    vo.setHasLiked(1);
                }

                // 将vo添加到集合
                voList.add(vo);
            }
        }
        // 4.将voList设置到分页对象
        pageBeanVo.setItems(voList);

        // 5.返回分页对象
        return ResponseEntity.ok(pageBeanVo);
    }

    // 查询推荐动态
    public ResponseEntity findRecommendMovementByPage(Integer pageNum, Integer pageSize) {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.查询推荐动态详情
        PageBeanVo pageBeanVo = movementService.findRecommendMovementByPage(userId, pageNum, pageSize);
        // 3.封装vo
        // 3-1 声明voList
        List<MovementVo> voList = new ArrayList<>();
        // 3-2 获取movementList
        List<Movement> movementList = (List<Movement>) pageBeanVo.getItems();
        // 3-3 遍历movementList
        if (CollectionUtil.isNotEmpty(movementList)) {
            for (Movement movement : movementList) {
                // 查询userInfo
                UserInfo userInfo = userInfoService.findByUserId(movement.getUserId());

                // 创建vo
                MovementVo vo = new MovementVo();
                vo.setUserInfo(userInfo);
                vo.setMovement(movement);

                // 点赞是否标记
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, userId, movement.getId().toHexString()))) {
                    vo.setHasLiked(1);
                }

                // 喜欢是否标记
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, userId, movement.getId().toHexString()))) {
                    vo.setHasLoved(1);
                }

                // 添加到集合
                voList.add(vo);
            }
        }
        // 4.将voList设置到分页对象
        pageBeanVo.setItems(voList);
        // 5.返回分页对象
        return ResponseEntity.ok(pageBeanVo);
    }

    @DubboReference
    private CommentService commentService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // 点赞
    public ResponseEntity movementLike(String publishId) {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.查询动态详情
        Movement movement = movementService.findById(new ObjectId(publishId));
        // 3.封装comment
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis()); // 点赞时间
        comment.setPublishId(new ObjectId(publishId)); // 动态id
        comment.setCommentType(1); // 类型-点赞
        comment.setUserId(userId); // 操作人id
        comment.setPublishUserId(movement.getUserId()); // 动态发布人id
        // 4.调用rpc保存
        Integer likeCount = commentService.saveComment(comment);

        // 5.向redis存储点赞标记    :  movement_like:{userId}_{publishId} = 1
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, userId, publishId), "1");

        // 6.发送mq消息（推荐）
        mqMovementManager.sendMovement(userId, movement.getId(), MQMovementManager.MOVEMENT_LIKE);

        // 6.返回数量
        return ResponseEntity.ok(likeCount);
    }

    // 取消点赞
    public ResponseEntity movementDislike(String publishId) {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.调用rpc删除
        Integer likeCount = commentService.removeComment(userId, new ObjectId(publishId), 1);
        // 3.从redis中删除点赞标记
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, userId, publishId));
        // 4.返回数量
        return ResponseEntity.ok(likeCount);
    }

    // 喜欢
    public ResponseEntity movementLove(String publishId) {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.查询动态详情
        Movement movement = movementService.findById(new ObjectId(publishId));
        // 3.封装comment对象
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis()); // 喜欢时间
        comment.setPublishId(movement.getId());// 动态id
        comment.setCommentType(3); // 类型-喜欢
        comment.setUserId(userId); // 操作人id
        comment.setPublishUserId(movement.getUserId()); // 动态发布人id
        // 4.调用rpc保存
        Integer loveCount = commentService.saveComment(comment);

        // 5. 向redis中存储喜欢标记   movement_love:{userId}_{publishId} = 1
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, userId, publishId), "1");

        // 6.返回喜欢数量
        return ResponseEntity.ok(loveCount);
    }

    // 取消喜欢
    public ResponseEntity movementUnlove(String publishId) {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.根据三个条件调用rpc删除
        Integer loveCount = commentService.removeComment(userId, new ObjectId(publishId), 3);
        // 3.从redis中删除喜欢标记
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, userId, publishId));
        // 4.返回喜欢数量
        return ResponseEntity.ok(loveCount);
    }

    // 单条动态查询
    public ResponseEntity findMovementDetail(String publishId) {
        // 1.查询动态详情
        Movement movement = movementService.findById(new ObjectId(publishId));
        // 2.封装movementVo
        // 2-1 查询userInfo
        UserInfo userInfo = userInfoService.findByUserId(movement.getUserId());
        // 2-2 创建vo
        MovementVo vo = new MovementVo();
        vo.setUserInfo(userInfo);
        vo.setMovement(movement);
        // 3.返回vo
        return ResponseEntity.ok(vo);
    }

    // 评论列表
    public ResponseEntity findCommentVoByPage(String publishId, Integer pageNum, Integer pageSize) {
        // 获取线程内userId
        Long userId = UserHolder.get().getId();
        // 1.查询评论分页对象
        PageBeanVo pageBeanVo = commentService.findCommentByPage(new ObjectId(publishId), 2, pageNum, pageSize);
        // 2. 封装commentVo
        // 2-1 声明voList
        List<CommentVo> voList = new ArrayList<>();
        // 2-2 获取commentList
        List<Comment> commentList = (List<Comment>) pageBeanVo.getItems();
        // 2-3 遍历commentList
        if (CollectionUtil.isNotEmpty(commentList)) {
            for (Comment comment : commentList) {
                // 查询userInfo
                UserInfo userInfo = userInfoService.findByUserId(comment.getUserId());
                // 创建vo
                CommentVo vo = new CommentVo();
                vo.setId(comment.getId().toHexString()); // 评论id
                vo.setAvatar(userInfo.getAvatar());// 评论人头像
                vo.setNickname(userInfo.getNickname()); // 评论人昵称
                vo.setContent(comment.getContent());// 评论内容
                vo.setCreateDate(DateUtil.formatTime(new Date(comment.getCreated())));// 评论时间
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_COMMENT_LIKE, userId, comment.getId())))
                {
                    vo.setHasLiked(1);
                }
                // 添加到list
                voList.add(vo);
            }
        }
        // 3.将voList设置到分页对象
        pageBeanVo.setItems(voList);
        // 4.返回分页对象
        return ResponseEntity.ok(pageBeanVo);
    }

    // 发表评论
    public ResponseEntity movementComment(String publishId, String content) {

        //先查redis中否冻结了评论
        if (stringRedisTemplate.hasKey("freeze:say")) {
            return ResponseEntity.status(500).body("禁止评论");
        }

        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.查询动态详情
        Movement movement = movementService.findById(new ObjectId(publishId));
        // 3.封装comment对象
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis());// 评论时间
        comment.setPublishId(movement.getId());// 动态id
        comment.setCommentType(2); // 类型-评论
        comment.setUserId(userId); // 操做人
        comment.setPublishUserId(movement.getUserId()); // 动态发布人
        comment.setContent(content);// 评论内容
        // 4.调用rpc保存
        commentService.saveComment(comment);

        return ResponseEntity.ok("发言成功");
    }

    // 评论点赞
    public ResponseEntity movementCommentLike(String movementCommentLike) {
        // 获取线程内userId
        Long userId = UserHolder.get().getId();
        Comment commentById = commentService.findById(new ObjectId(movementCommentLike));
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementCommentLike));
        comment.setCommentType(7);
        comment.setUserId(userId);
        comment.setPublishUserId(comment.getUserId());//被操作对象所属人
        comment.setCreated(System.currentTimeMillis());
        Integer commentLikeCount = commentService.saveComment(comment);
        // 5. 向redis中存储点赞标记   movement_love:{userId}_{publishId} = 1
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_COMMENT_LIKE, userId, commentById.getId()), "7");
        //返回
        return ResponseEntity.ok(commentLikeCount);

    }

    // 评论点赞-取消
    public ResponseEntity movementCommentDislike(String movementCommentDislike) {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.根据三个条件调用rpc删除
        Integer commentLikeCount = commentService.removeComment(userId, new ObjectId(movementCommentDislike), 6);
        // 3.从redis中删除点赞标记
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_COMMENT_LIKE, userId, movementCommentDislike));
        //返回
        return ResponseEntity.ok(commentLikeCount);
    }
}
